﻿namespace Blaze.Editor
{
    using System;
    using System.IO;
    using System.Reflection;
    using Build;
    using Configs;
    using EditorOnly;
    using Framework;
    using Framework.Logging;
    using Newtonsoft.Json;

    /// <summary>
    /// 编辑器配置。
    /// <remarks>
    /// 对应blaze_editor.config.txt，优先加载Assets/Editor目录下的配置，若不存在则加载Assets/Blaze/Editor下的配置。
    /// </remarks>
    /// </summary>
    public sealed class BlazeEditorConfig
    {
        /// <summary>
        /// 获取配置文件名。
        /// </summary>
        public const string FileName = "blaze_editor_config.txt";

        /// <summary>
        /// 获取<see cref="BlazeEditorConfig"/>的唯一实例。
        /// </summary>
        public static BlazeEditorConfig Instance
        {
            get
            {
                if (mInstance == null || mInstance.mShouldReload)
                {
                    var path = ProjectPath.GetAssets("Editor/" + FileName);
                    if (File.Exists(path))
                        mInstance = Create(path);
                    else
                        mInstance = Create(ProjectPath.GetAssets("Blaze/Editor/" + FileName));
                }
                return mInstance;
            }
        }

        /// <summary>
        /// 获取或设置所有启用的资源规则。
        /// </summary>
        public string[] AssetRules
        {
            get
            {
                if (mAssetRules == null)
                    mAssetRules = new string[0];
                return mAssetRules;
            }
            set { mAssetRules = value; }
        }

        /// <summary>
        /// 获取或设置启动场景路径。
        /// </summary>
        public string BootstrapScene { get; set; }

        /// <summary>
        /// 获取或设置默认的<see cref="BuildConfig"/>所在的命名空间。
        /// </summary>
        public string BuildConfigNamespace { get; set; }

        /// <summary>
        /// 获取或设置所有的构建流程配置。
        /// </summary>
        public BuildPipelineConfig[] BuildPipelines { get; set; }

        /// <summary>
        /// 获取或设置渠道的快捷方式数组。
        /// </summary>
        public ServerShortcutConfig[] Channels
        {
            get
            {
                if (mChannels == null)
                    mChannels = new ServerShortcutConfig[0];
                return mChannels;
            }
            set { mChannels = value; }
        }

        /// <summary>
        /// 获取或设置导出工具的名称。
        /// </summary>
        public string ConfigExportTool { get; set; }

        /// <summary>
        /// 获取或设置入口服务器的地址快捷方式数组。
        /// </summary>
        public ServerShortcutConfig[] EntryServers
        {
            get
            {
                if (mEntryServers == null)
                    mEntryServers = new ServerShortcutConfig[0];
                return mEntryServers;
            }
            set { mEntryServers = value; }
        }

        /// <summary>
        /// 获取或设置登录服务器的地址快捷方式数组。
        /// </summary>
        public ServerShortcutConfig[] LoginServers
        {
            get
            {
                if (mLoginServers == null)
                    mLoginServers = new ServerShortcutConfig[0];
                return mLoginServers;
            }
            set { mLoginServers = value; }
        }

        /// <summary>
        /// 获取或设置工程名称。
        /// </summary>
        public string ProjectName { get; set; }

        /// <summary>
        /// 获取所有资源目录路径（相对于Assets）。
        /// </summary>
        public string[] ResourceDirectories { get; set; }

        /// <summary>
        /// 从指定文件创建编辑器配置。
        /// </summary>
        /// <param name="path">配置文件的路径</param>
        public static BlazeEditorConfig Create(string path)
        {
            var text = File.ReadAllText(path);
            var settings = new JsonSerializerSettings();
            settings.Converters.Add(new BuildActionConfigConverter());
            var ret = JsonConvert.DeserializeObject<BlazeEditorConfig>(text, settings);
            var dir = Path.GetDirectoryName(path);
            if (mFileWatcher == null)
            {
                mFileWatcher = new FileSystemWatcher(dir, FileName)
                {
                    IncludeSubdirectories = false,
                    EnableRaisingEvents = true
                };
                mFileWatcher.Changed += (s, e) =>
                {
                    ret.mShouldReload = true;
                    mLog.Debug("[BlazeEditorConfig]config file changed");
                };
            }
            return ret;
        }

        /// <summary>
        /// 获取指定名称的<see cref="BuildConfig"/>类型。
        /// </summary>
        /// <param name="name"></param>
        /// <returns></returns>
        public Type GetBuildConfigType(string name)
        {
            if (!string.IsNullOrEmpty(BuildConfigNamespace))
                name = string.Format("{0}.{1}", BuildConfigNamespace, name);
            return Assembly.GetExecutingAssembly().GetType(name);
        }

        private static FileSystemWatcher mFileWatcher;
        private static BlazeEditorConfig mInstance;
        private static readonly Log mLog = LogManager.GetLogger(typeof(BlazeEditorConfig));
        private string[] mAssetRules;
        private ServerShortcutConfig[] mChannels;
        private ServerShortcutConfig[] mEntryServers;
        private ServerShortcutConfig[] mLoginServers;
        private bool mShouldReload;
    }
}